#include "AstNodeForStatement.h"

/*

   FOR i = b,e
     stmt_list
   NEXT


   i=b
lab1:
    i<=e?
      n: goto lab2
   stmt_list
   goto lab1
lab2:
*/
  

AstNodeForStatement::AstNodeForStatement(
    u2  cycleVariableIndex,
    AstNodeExpression * startExpression,
    AstNodeExpression * endExpression,
    AstNodeExpression * step,
    AstNodeStatementList * body)
{
  AstNodeLValue * cycleVariableLValue;
  AstNodeExpressionVariable * cycleVariableExpression;

  cycleVariableLValue=
    new AstNodeLValue(cycleVariableIndex);

  startStatement=new
    AstNodeAssignment(cycleVariableLValue, startExpression);

  cycleVariableExpression=new AstNodeExpressionVariable(cycleVariableIndex);

  cond=new AstNodeCompareExpression(cycleVariableExpression,endExpression,
    AstNodeCompareExpression::_less_equal);


  // nextIterStatement -> cycleVariableLValue = cycleVariableExpre '+' step
  cycleVariableLValue=
    new AstNodeLValue(cycleVariableIndex);
  cycleVariableExpression=
    new AstNodeExpressionVariable(cycleVariableIndex);
  AstNodeExpression * incrExpression=
      new AstNodeBinaryOperator('+',cycleVariableExpression,step);
  nextIterStatement=new 
    AstNodeAssignment(cycleVariableLValue, incrExpression);

  this->body=body;
}

void AstNodeForStatement::dump()
{
  printf("FOR STATEMENT\n");
}

int AstNodeForStatement::compile(ClassFile * klass, MethodInfo * method)
{
  RelocTable relocOnFalse;
  u4 targetRepeat;
  u4 locGoto;

  startStatement->compile(klass,method);

  targetRepeat=method->getAP();

  u1 opcode=cond->getOpcodeForFalse();
  cond->compile(klass,method);
  relocOnFalse.push_back(method->getAP());
  method->assemble(opcode,0);

  body->compile(klass,method);

  nextIterStatement->compile(klass,method);

  locGoto=method->getAP();
  
  method->assemble(OPC_goto,targetRepeat-locGoto);

  relocOnFalse.reloc(method,method->getAP());
  return 0;
}


